import router from "../router";
import Layers from "@/lang/layers";

/**
 * 静态菜单，前期开发，前期可以采用纯前端的菜单配置方式。
 * 等到项目中后期，可以将这一部分的配置移到数据库中。
 *
 * 右侧导航条
 * @type {*[]}
 */
const menu = [
    {
        title: '首页', icon: 'fa fa-fw fa-dashboard', url: 'main/home.vue', key: 'home'
    },
    {
        title: '用户配置', icon: 'fa fa-fw fa-user', key: 'auth',
        children: [
            {title: '用户管理', icon: '', url: 'auth/user', key: 'user'}
            , {title: '角色管理', icon: '', url: 'auth/role', key: 'role'}
            , {title: '部门管理', icon: '', url: 'auth/dept', key: 'dept'}
            , {title: '星级配置', icon: '', url: 'auth/star', key: 'star'}
            , {title: '用户选择面板', icon: '', url: 'auth/user/select', key: 'select'}
        ]
    },
    {
        title: '初始化', icon: 'fa fa-fw fa-hourglass-3', key: 'init',
        children: [
            {title: '角色管理', icon: '', url: 'init/role', key: 'role'}
            , {title: '菜单管理', icon: '', url: 'init/menu', key: 'menu'}
            , {title: '权限管理', icon: '', url: 'init/permit', key: 'permit'}
            , {title: '组织机构', icon: '', url: 'init/organization', key: 'organization'}
        ]
    },
    {
        title: '系统关联', icon: 'fa fa-fw fa-hourglass-start', key: 'schedule',
        children: [
            {title: '定时任务', icon: '', url: 'sys/schedule/quartz', key: 'quartz'}
            , {title: '定时广播', icon: '', url: 'sys/schedule/broad', key: 'broad'}
            , {title: '参数配置', icon: '', url: 'sys/variable', key: 'variable'}
            , {title: '数据字典', icon: '', url: 'sys/dic', key: 'dic'}
        ]
    },
    {
        title: '通知管理', icon: 'fa fa-fw fa-volume-up', key: 'msg',
        children: [
            {title: '消息模版', icon: '', url: 'sys/msg/message', key: 'message'}
            , {title: '系统消息', icon: '', url: 'sys/msg/notice', key: 'notice'}
            , {title: '短信配置', icon: '', url: 'sys/msg/sms', key: 'sms'}
            , {title: '系统公告', icon: '', url: 'sys/msg/bulletin', key: 'bulletin'}
        ]
    },
    {
        title: 'Kettle', icon: 'fa fa-fw fa-object-group', key: 'kettle',
        children: [
            {title: '资产清单', icon: '', url: 'kettle/script', key: 'script'}
            , {title: '运行日志', icon: '', url: 'kettle/log', key: 'log'}
            , {title: '共享变量', icon: '', url: 'kettle/variable', key: 'variable'}
        ]
    },
    {
        title: '文件管理', icon: 'fa fa-fw fa-folder-open-o', key: 'file',
        children: [
            {title: '应用', icon: '', url: 'sys/file/app', key: 'app'}
            , {title: 'Excel', icon: '', url: 'sys/file/excel', key: 'excel'}
            , {title: '图片', icon: '', url: 'sys/file/image', key: 'image'}
            , {title: '文件', icon: '', url: 'sys/file/file', key: 'file'}
        ]
    }
];

/**
 * 静态菜单，前期开发，前期可以采用纯前端的菜单配置方式。
 * 等到项目后期，可以将这一部分的配置移到数据库中。
 *
 * 顶部导航条
 * @type {*[]}
 */
const tools = [
    {
        title: '代码样例', icon: 'fa fa-fw fa-list', key: 'example',
        children: [
            {title: '数据表格', icon: '', url: 'example/DataTable.vue', key: 'table'}
            , {title: '表单(el-form)', icon: '', url: 'example/Form.vue', key: 'form'}
            , {title: '表单Plus(el-form)', icon: '', url: 'example/ElFormPlus.vue', key: 'el_form'}
            , {title: '万能表单Ultra', icon: '', url: 'example/FastFormUltra.vue', key: 'smart_form'}
            , {title: 'ListView', icon: '', url: 'example/ListView.vue', key: 'list_view'}
            , {title: 'TestTree', icon: '', url: 'tools/TestTree.vue', key: 'tree'}
        ]
    },
    {
        title: '功能件', icon: 'fa fa-fw fa-list', key: 'tools',
        children: [
            {title: '图表', icon: '', url: 'tools/Charts.vue', key: 'charts'}
            , {title: '聊天框', icon: '', url: 'tools/Chat.vue', key: 'chat'}
            , {title: '消息盒子', icon: '', url: 'tools/InfoBox.vue', key: 'info_box'}
            , {title: '产品列表', icon: '', url: 'tools/ProductList.vue', key: 'product_list'}
            , {title: '时间线', icon: '', url: 'tools/TimeLine.vue', key: 'time_line'}
        ]
    },
    {
        title: '算法', icon: 'fa fa-fw fa-gamepad', key: 'turing',
        children: [
            {title: '代码生成', icon: '', url: 'turing/gen', key: 'gen'}
            , {title: '用户海报', icon: '', url: 'turing/poster', key: 'poster'}
            , {title: '磁盘映射', icon: '', url: 'turing/resource', key: 'resource'}
        ]
    },
    {
        title: '常规界面', icon: 'fa fa-fw fa-gamepad', key: 'normal',
        children: [
            {title: '403', icon: '', url: 'error/E403.vue', key: 'E403'}
            , {title: '404', icon: '', url: 'error/E404.vue', key: 'E404'}
            , {title: '500', icon: '', url: 'error/E500.vue', key: 'E500'}
            , {title: '锁屏', icon: '', url: 'lock.vue', key: 'lock'}
        ]
    },
    {
        title: '邮箱', icon: 'fa fa-fw fa-envelope', key: 'mail',
        children: [
            {title: '发件箱', icon: '', url: 'sys/mail/compose.vue', key: 'compose'}
            , {title: '邮件', icon: '', url: 'sys/mail/inbox.vue', key: 'inbox'}
            , {title: '收件箱', icon: '', url: 'sys/mail/read.vue', key: 'read'}
        ]
    },
    {
        title: 'GIS', icon: 'fa fa-fw  fa-map', key: 'gis',
        children: [
            {title: '4490坐标', icon: '', url: 'turing/gis/4490.vue', key: '4490'}
            , {title: '图片转换', icon: '', url: 'turing/gis/base64.vue', key: 'base64'}
            , {title: '设备展示', icon: '', url: 'turing/gis/show.vue', key: 'show'}
            , {title: '平面图', icon: '', url: 'turing/gis/graph.vue', key: 'graph'}
        ]
    }
];

/**
 * 静态菜单，前期开发，前期可以采用纯前端的菜单配置方式。
 * 等到项目后期，可以将这一部分的配置移到数据库中。
 *
 * 顶部导航条
 * @type {*[]}
 */
const $static = [
    {
        title: '文档管理', icon: 'fa fa-fw fa-list', key: 'doc',
        children: [
            {title: 'ICON', icon: '', url: 'sys/doc/icons', key: 'icons'}
            , {title: '使用文档', icon: '', url: 'sys/doc/blog', key: 'blog'}
            , {title: 'OpenAPI', icon: '', url: 'sys/doc/open-api', key: 'open-api'}
            , {title: '接口文档', icon: '', url: 'sys/doc/api-mapping', key: 'api-mapping'}
            , {title: 'MyBatis', icon: '', url: 'sys/doc/ibatis', key: 'ibatis'}
            , {title: '服务器信息', icon: '', url: 'sys/doc/props', key: 'props'}
        ]
    },
    {
        title: '系统日志', icon: 'fa fa-fw fa-list', key: 'log',
        children: [
            {title: '登录日志', icon: '', url: 'sys/log/login', key: 'login'}
            , {title: '访问日志', icon: '', url: 'sys/log/access/index.vue', key: 'access'}
            , {title: '运行日志', icon: '', url: 'sys/log/slf4j', key: 'slf4j'}
        ]
    }
];

/**
 * 递归处理菜单
 * @param routes    路由数组
 * @param menus     菜单列表
 * @param key       key
 */
function parseMenu(routes, menus, key) {
    for (let i = 0; i < menus.length; i++) {
        const menu = menus[i];
        menu.path = key + '/' + menu.key;
        menu.name = menu.path.replace('/', '_');
        if (Layers.isNotEmpty(menu.url)) {
            // 添加到路由
            routes.push({
                name: menu.name,
                label: menu.title,
                path: menu.path,
                component: () => import(`@/view/${menu.url}`)
            });
        } else {
            if (menu.children !== undefined) {
                // 递归
                parseMenu(routes, menu.children, menu.path);
            }
        }
    }
}

/**
 * 查找菜单
 *
 * @param key   唯一值
 * @param menus 菜单列表
 * @returns {*}
 */
function queryMenuByKey(key, menus) {
    for (let i = 0; i < menus.length; i++) {
        if (menus[i].key === key) {
            return menus[i];
        }
    }
}

/**
 * 获取菜单配置的原始数据
 *
 * @param keys {[String]}   路径数组
 * @param level {Number}    keys数组长度
 * @param menus {[any]}     菜单列表
 */
function queryMenuByKeyPath(keys, level, menus) {
    let m = queryMenuByKey(keys[level], menus);
    if (m === undefined) {
        throw new NullPointerException('menu is undefined: ' + keys[level]);
    }
    level++;
    if (level === keys.length) {
        return m;
    } else {
        let children = m.children;
        if (children === null) {
            throw new NullPointerException("menu' children is undefined: " + m);
        }
        return queryMenuByKeyPath(keys, level, children);
    }
}

/**
 * 菜单管理，包含了路由的管理
 * @constructor
 */
export default class MenuManager {

    /**
     * 缓存全部的菜单数据
     */
    static fully_menus;
    /**
     * 缓存全部的菜单数据
     */
    static fully_routes;

    constructor() {
    }


    /**
     * 将菜单配置信息转为懒加载的数据格式。
     *
     * 这个函数，从写法上，直接限定了菜单栏发最大层级只有3级，
     * 更多层级是无效的，代码不会报错，但是也不会进行解析。
     *
     * 注意：
     * 虽然 path 有路径层级，但是实际上是同级路由，不具备上下级关系；
     * 所有的路由，都是 index.vue 界面的子路由。
     *
     * @param menus 树形结构的菜单数据
     * @returns {[]}
     */
    static converterMenusToRoutes(menus) {
        let routes = [];
        parseMenu(routes, menus, '');
        return routes;
    }


    /**
     * 右侧菜单栏
     *
     * @returns {Promise<*[]>}
     */
    static getMenu() {
        return new Promise((resolve, reject) => {
            if (menu !== undefined) {
                resolve(menu);
            } else {
                // TODO: load menu
                resolve([]);
            }
        });
    };

    /**
     * 获取工具栏
     *
     * @returns {Promise<*[]>}
     */
    static getTools() {
        return new Promise((resolve, reject) => {
            if (tools !== undefined) {
                resolve(tools);
            } else {
                // TODO: load menu
                resolve([]);
            }
        });
    };

    /**
     * 获取静态菜单
     *
     * @returns {Promise<*[]>}
     */
    static async getStaticMenus() {
        return new Promise((resolve, reject) => {
            if ($static !== undefined) {
                resolve($static);
            } else {
                // TODO: load menu
                resolve([]);
            }
        });
    };

    /**
     * TODO: 按照项目需求查询项目的菜单栏配置
     * 异步载入菜单列表，格式要求参照 menu 即可
     *
     * @return {Promise<[]>}
     */
    static loadMenus() {
        let all = [];
        all.push(this.getMenu());
        all.push(this.getTools());
        all.push(this.getStaticMenus());
        return Promise.all(all).then(([menu, tools, $static]) => {
            let ret = [];
            for (let i = 0; i < menu.length; i++) {
                ret.push(menu[i]);
            }
            for (let i = 0; i < tools.length; i++) {
                ret.push(tools[i]);
            }
            for (let i = 0; i < $static.length; i++) {
                ret.push($static[i]);
            }
            return ret;
        });
    }

    /**
     * 添加动态菜单，可以按自己实际需求，寻找合适的时机加载菜单，
     * 至少保证要在路由初始化完成之后。
     */
    static addDynamicMenus() {
        this.loadMenus().then((menus) => {
            // 缓存全量菜单数据
            MenuManager.fully_menus = menus;
            // 配置数据转路由
            const routes = this.converterMenusToRoutes(menus);
            // 缓存全部路由数据
            MenuManager.fully_routes = routes;
            router.addRoutes([
                {
                    name: "_index",
                    path: '/',
                    label: '首页',
                    component: () => import('@/view/index.vue'),
                    children: routes
                },{
                    name: "_login",
                    path: '/login',
                    label: '登录界面',
                    component: () => import('@/view/login.vue'),
                },{
                    name: "_register",
                    path: '/register',
                    label: '注册界面',
                    component: () => import('@/view/register.vue'),
                },{
                    name: "_lock",
                    path: '/lock',
                    label: '锁屏',
                    component: () => import('@/view/lock.vue'),
                }
            ]);
        });
    };
}

